﻿namespace NJQuery {
	using System;
	using System.Web.UI;
	using System.Collections.Specialized;
	using System.Globalization;
	using System.Diagnostics.CodeAnalysis;

	/// <summary>
	/// Server control used to generate a <see href="http://jqueryui.com/demos/datepicker/">jQuery UI Datepicker widget</see> inline in the page.
	/// </summary>
	public class Calendar : DatePickerBase {

		//TODO: The biggest problem with this control is currently, it does not persist the current month/year when it differs from selected/current

		#region Constants

		private const string serverIso8601 = "yyyy-MM-dd";
		private const string clientIso8601 = "yy-mm-dd";

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="Calendar"/> class.
		/// </summary>
		public Calendar() : base(HtmlTextWriterTag.Div) { }

		#endregion


		#region Properties: Additional

		/// <summary>
		/// Gets or sets the value of the date selected in the calendar.
		/// </summary>
		public override DateTime? SelectedDate {
			get { return ViewState["SelectedDate"] as DateTime?; }
			set { ViewState["SelectedDate"] = value; }
		}

		#endregion


		#region Properties: Sub-control

		/// <summary>
		/// Gets the rendered element ID of the hidden field used to round-trip the <see cref="SelectedDate"/> property.
		/// </summary>
		public virtual string SelectedDateClientId {
			get { return string.Format(CultureInfo.InvariantCulture, "__{0}_SelectedDate", ClientID); }
		}

		#endregion


		#region Methods: Rendering hooks

		/// <summary>
		/// Sends server control content to a provided <see cref="HtmlTextWriter"/> object, which writes the content to be rendered to the client.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="writer">A <see cref="HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
		protected override void Render(HtmlTextWriter writer) {
			base.Render(writer);

			ClientScriptManager clientScript = Page.ClientScript;
			clientScript.RegisterForEventValidation(new PostBackOptions(this));

			DateTime? selectedDate = SelectedDate;
			clientScript.RegisterHiddenField(SelectedDateClientId, selectedDate.HasValue ? selectedDate.Value.ToString(serverIso8601, CultureInfo.InvariantCulture) : string.Empty);
		}

		/// <summary>
		/// Creates the properties object that will be rendered as the jQuery UI initialization options.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="properties">A <see cref="PropertyCollection"/> object that will become the jQuery UI initialization options.</param>
		protected override void AddInitProperties(PropertyCollection properties) {
			base.AddInitProperties(properties);

			properties.AddValue("dateFormat", clientIso8601);

			DateTime? selectedDate = SelectedDate;
			if(selectedDate.HasValue) properties.AddValue("defaultDate", selectedDate.Value, false);

		}

		/// <summary>
		/// Renders additional client "onSelect" event script required by the specific control.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected override void RenderAdditionalOnSelectScript(ScriptBuilder script) {

			//Persist SelectedDate
			script.NewLine();
			script.RenderIdSelector(SelectedDateClientId);
			script.Append(".val(dateText);");

		}

		#endregion


		#region Methods: Post data

		/// <summary>
		/// Processes postback data for an ASP.NET server control.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="postDataKey">The key identifier for the control.</param>
		/// <param name="postCollection">The collection of all incoming name values.</param>
		/// <returns>True if the server control's state changes as a result of the postback; otherwise, false.</returns>
		protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection) {

			Page.ClientScript.ValidateEvent(postDataKey);

			DateTime? newSelectedDate;
			if(Utility.TryParse(postCollection[SelectedDateClientId], out newSelectedDate) && newSelectedDate != SelectedDate) {
				SelectedDate = newSelectedDate;
				return true;
			}

			return false;
		}

		/// <summary>
		/// Signals the server control to notify the ASP.NET application that the state of the control has changed.
		/// This method is used primarily by control developers.
		/// </summary>
		protected override void RaisePostDataChangedEvent() {
			OnSelectedDateChanged(EventArgs.Empty);
		}

		#endregion


	}

}